
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include <sstream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/time.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <signal.h>

#include <net/if.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "file_server.h"
#include "define.h"
#include "list.h"
#include "securec.h"

using namespace std;
using namespace OHOS;

#define MAX_CLIENT      5
#define MAX_FD_NUM      5
#define MIN_IP_LEN      15
#define RECV_TIMEOUT    5

#define FILE_SERVER_DEBUG
#ifdef  FILE_SERVER_DEBUG
#define SER_DBG(fmt, args...)   printf("[DEBUG][%s|%d]" fmt "\n", __func__, __LINE__, ##args)
#define SER_ERR(fmt, args...)   printf("[ERROR][%s|%d]" fmt "\n", __func__, __LINE__, ##args)
#else
#define SER_DBG(fmt, args...)   do {} while (0)
#define SER_DBG(fmt, args...)   do {} while (0)
#endif

typedef struct {
    List<std::string> *g_fileList;

    pthread_t g_thread;
    pthread_mutex_t g_mutex;

    int g_mutexInit;
    int g_running;

    int g_fileIsTrans;

    CheckDialog g_dialog;
    void *g_data;
} FileServer;

typedef struct {
    int fd;
    char ip[32];
} ClientInfo;

static FileServer *g_server = nullptr;

// **********************************************  broadcast server ******************************************************************************************//
static int GetLocalIpAddress(char *ip, int size)
{
#define WLAN_NAME   "wlan0"
    struct ifreq ifr;
    int fd = -1;
    int ret = 0;

    if (ip == NULL || size <= 0) {
        SER_ERR("invalid params!");
        return -1;
    }

    (void)memset_s(&ifr, sizeof(ifr), 0x00, sizeof(ifr));
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        SER_ERR("socket failed!");
        return -1;
    }

    (void)strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), WLAN_NAME, strlen(WLAN_NAME));
    ret = ioctl(fd, SIOCGIFADDR, &ifr);
    if (ret < 0) {
        SER_ERR("ioctl failed!");
        close(fd);
        return -1;
    }

    (void)strcpy_s(ip, size, inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr));
    SER_DBG("ip : %s", ip);

    close(fd);

    return 0;
}

static void *ServerBroadcast(void *p)
{
#define IP_BROAD_MSG    "ip discovery broadcast@%s"
    pthread_t *pid = (pthread_t *)p;
    pthread_detach(pthread_self());

    char msg[256] = {0};
    char ip[32] = {0};
    struct sockaddr_in addrto;
    int opt = 1;
    int sockfd = -1;

    if (GetLocalIpAddress(ip, sizeof(ip)) < 0) {
        SER_ERR("GetLocalIpAddress failed!");
        (void)sprintf_s(msg, sizeof(msg), IP_BROAD_MSG, "0.0.0.0");
    } else {
        (void)sprintf_s(msg, sizeof(msg), IP_BROAD_MSG, ip);
    }

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        SER_ERR("create socket failed!");
        *pid = 0;
        return NULL;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) < 0) {
        SER_ERR("setsockopt failed!");
        *pid = 0;
        close(sockfd);
        return NULL;
    }

    memset(&addrto, 0x00, sizeof(addrto));
    addrto.sin_family = AF_INET;
    addrto.sin_port = htons(BROADCAST_SERVER);
    addrto.sin_addr.s_addr = inet_addr("255.255.255.255");

    while (1) {
        const int sleepTime = 5;
        int ret = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *)&(addrto), sizeof(addrto));
        if (ret < 0) {
            SER_ERR("socket UDP send failed! \n");
            break;
        }
        sleep(sleepTime);
    }

    *pid = 0;
    close(sockfd);

    return NULL;
}
// ************************************************************************************************************************************************************* //
static void RequestSetupAck(char *buff, int cmd, int cp)
{
    if (cmd == -1) {
        sprintf(buff, "RTP/1.0 401");
    } else {
        sprintf(buff, "RTP/1.0 200 OK\r\nACK Transport:RTP/AVP;client_port=%d\r\n", cp);
    }
}

static void RequestPlayAck(char *buff, int cmd, const char *name, int size)
{
    if (cmd == -1) {
        sprintf(buff, "RTP/1.0 401");
    } else {
        sprintf(buff, "RTP/1.0 200 OK\r\nACK CMD:start\r\nFILENAME:%s\r\nFLESIZE:%d\r\n", name, size);
    }
}

static int GetBufferInfo(const char *src, const char *s_key, char e_key, char *buff, int bsize)
{
    char *ps, *pe;
    int length = 0;

    if (src == NULL || buff == NULL || bsize <= 0) {
        SER_ERR("NULL POINT!");
        return -1;
    }

    if (s_key == NULL) {
        ps = (char *)src;
    } else {
        ps = (char *)strstr(src, s_key) + strlen(s_key);
    }

    if (ps == NULL) {
        return -1;
    }

    pe = (char *)strchr(ps, e_key);
    if (pe == NULL) {
        length = strlen(ps);
    } else {
        length = ps - pe;
    }

    return strncpy_s(buff, bsize, ps, length);
}

static int GetFileInfo(const char *psrc, char *name, int size, int *fsize)
{
#define KEY_NAME    "FILENAME:"
#define KEY_SIZE    "FILESIZE:"
    char *ps, *pe;
    char tmp[32] = {0};

    if (psrc == NULL || name == NULL || fsize == NULL || size <= 0) {
        return -1;
    }
    ps = (char *)strstr(psrc, KEY_NAME);
    if (ps == NULL) {
        return -1;
    }
    ps += strlen(KEY_NAME);
    pe = (char *)strchr(ps, '\r');
    if (!pe) {
        return -1;
    }
    (void)strncpy_s(name, size, ps, pe - ps);

    ps = (char *)strstr(psrc, KEY_SIZE);
    if (!ps) {
        return -1;
    }
    ps += strlen(KEY_SIZE);
    pe = (char *)strchr(ps, '\r');
    if (!pe) {
        return -1;
    }
    (void)strncpy_s(tmp, sizeof(tmp), ps, pe - ps);
    *fsize = atoi(tmp);

    return 0;
}

// **************************************************socket start*********************************************************//
static int SocketOpen(int port, const char *ip)
{
    int sockfd;
    int on = 1;
    struct sockaddr_in addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        SER_ERR("socket!");
        return -1;
    }

    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    if (ip == NULL) {
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
    } else {
        addr.sin_addr.s_addr = inet_addr(ip);
    }

    if (::bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0) {
        SER_ERR("bind failed!");
        close(sockfd);
        return -1;
    }

    if (listen(sockfd, MAX_FD_NUM) < 0) {
        SER_ERR("listen failed!");
        close(sockfd);
        return -1;
    }

    return sockfd;
}

static int SocketAcceptClient(int sockfd, char *ipBuff, int ipSize, int *port)
{
    int clientFd;
    socklen_t len = 0;
    struct sockaddr_in addr;

    if (sockfd < 0) {
        return -1;
    }
    memset(&addr, 0x00, sizeof(addr));
    len = sizeof(addr);

    clientFd = accept(sockfd, (struct sockaddr *)&addr, &len);
    if (clientFd < 0) {
        SER_ERR("accept failed!");
        return -1;
    }

    if (ipBuff != NULL && ipSize > MIN_IP_LEN) {
        memset(ipBuff, 0x00, ipSize);
        (void)strcpy_s(ipBuff, ipSize, inet_ntoa(addr.sin_addr));
    }

    if (port) {
        *port = ntohs(addr.sin_port);
    }

    return clientFd;
}

static int SocketRecv(int sockfd, void *buffer, int size, int tms)
{
    if (sockfd < 0 || buffer == NULL || size <= 0) {
        return -1;
    }

    if (tms > 0) {
        struct timeval timeout;
        timeout.tv_sec = tms;
        timeout.tv_usec = 0;
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
    }

    return recv(sockfd, buffer, size, 0);
}

static int SocketSend(int sockfd, void *buffer, int length, int tms)
{
    if (sockfd < 0 || buffer == NULL || length <= 0) {
        return -1;
    }

    if (tms > 0) {
        struct timeval timeout;
        timeout.tv_sec = tms;
        timeout.tv_usec = 0;
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
    }

    return send(sockfd, buffer, length, 0);
}

static void SocketClose(int sockfd)
{
    if (sockfd >= 0) {
        close(sockfd);
    }
}
// **************************************************socket end*********************************************************//
static int SocketSendFile(const FILE *pFile, int filesize, int port, const char *ipAddr)
{
    int sockfd = 0;
    const int opt = 1;
    struct sockaddr_in addrto;

    if (pFile == NULL) {
        return -1;
    }

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        SER_ERR("socket failed!");
        return -1;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
        SER_ERR("set reuseaddr failed! \n");
        close(sockfd);
        return -1;
    }

    memset(&addrto, 0x00, sizeof(addrto));
    addrto.sin_family = AF_INET;
    addrto.sin_addr.s_addr = inet_addr(ipAddr);
    addrto.sin_port = htons(port);

    while (1) {
        const int sleepTime = 500000;
        char buff[4096] = {0};
        int sendBytes = 0;
        int readBytes = fread(buff, 1, sizeof(buff), (FILE *)pFile);
        if (readBytes <= 0) {
            sendto(sockfd, "quit", strlen("quit"), 0, (struct sockaddr *)&addrto, sizeof(struct sockaddr_in));
            break;
        }
        usleep(sleepTime); /* each package delay 500ms */
        sendBytes = sendto(sockfd, buff, readBytes, 0, (struct sockaddr *)&addrto, sizeof(struct sockaddr_in));
        if (sendBytes < 0) {
            SER_ERR("sendto failed!");
            break;
        }
    }

    close(sockfd);

    return 0;
}

static int SocketRecvFileWithProgress(FILE *pFile, unsigned long filesize, int port, CheckDialog pDialog, void *data)
{
    int sockfd = 0;
    struct sockaddr_in addrFrom;
    const int opt = 1;
    int err = 0;
    int retry = 0;
    unsigned long recv_size = 0;

    if (pFile == NULL || filesize == 0) {
        err = 1;
        goto RECV_EXIT;
    }

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        SER_ERR("socket failed!");
        err = 1;
        goto RECV_EXIT;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
        SER_ERR("set reuseaddr failed! \n");
        err = 1;
        goto RECV_EXIT;
    }

    memset(&addrFrom, 0x00, sizeof(addrFrom));
    addrFrom.sin_family = AF_INET;
    addrFrom.sin_addr.s_addr = INADDR_ANY;
    addrFrom.sin_port = htons(port);

    if (::bind(sockfd, (struct sockaddr *)&addrFrom, sizeof(addrFrom)) < 0) {
        SER_ERR("bind failed! \n");
        err = 1;
        goto RECV_EXIT;
    }

    while (recv_size < filesize) {
        char buff[4096] = {0};
        char *response_msg = "response from server";
        int len = sizeof(struct sockaddr_in);
        int ret = 0;
        struct timeval timeout = {2, 0};

        if (pDialog != NULL) {
            char msg[256] = {0};
            const int percentage = 100;
            int persent;
            if (recv_size > filesize) {
                recv_size = filesize;
            }

            persent = (int)((recv_size * percentage) / filesize);
            sprintf(msg, "接收中...(%d%%)", persent);
            pDialog(data, msg, DIALOG_PROGRESS, 0);
        }

        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
        ret = recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&addrFrom, (socklen_t *)&len);
        if (ret == 0) {
            continue;
        }

        if (ret < 0) {
            if (errno == EAGAIN || errno == EINTR) {
                if (++retry >= RECV_TIMEOUT) {
                    err = 1;
                    break;
                }
                continue;
            }
            err = 1;
            break;
        }

        retry = 0;

        if (ret != sizeof(buff) && strstr(buff, "quit")) {
            break;
        }
        recv_size += ret;

        if (pFile) {
            ret = fwrite(buff, 1, ret, pFile);
        }

        ret = sendto(sockfd, response_msg, strlen(response_msg), 0, (struct sockaddr *)&addrFrom, sizeof(addrFrom));
        if (ret < 0) {
            SER_ERR("sendto failed! \n");
            err = 1;
            break;
        }
    }

RECV_EXIT:
    if (pDialog != NULL) {
        const int delayTime = 5;
        if (err == 0) {
            pDialog(data, "数据接收完成!", DIALOG_OVER, delayTime);
        } else {
            pDialog(data, "数据接收失败!", DIALOG_OVER, delayTime);
        }
    }
    if (sockfd != -1) {
        close(sockfd);
    }

    return 0;
}
// ***************************************** file recv task thread start **************************************************************** //
static void *ClientConnectProcess(void *params)
{
    ClientInfo *cf = (ClientInfo *)params;
    int clientSockFd = -1;
    char *ip = NULL;
    int clientUPort = -1;
    int cmd = -1;
    int fileSize = 0;

    if (g_server == NULL) {
        return NULL;
    }

    if (cf == NULL) {
        return NULL;
    }

    clientSockFd = cf->fd;
    ip = cf->ip;

    while (1) {
        char rBuf[512] = {0};
        char sBuf[512] = {0};
        char method[20] = {0};
        int play = 0;
        int ret = 0;
        fd_set fdset;
        struct timeval tv = {5, 0};
        int recvLen = 0;
        char filename[256] = {0};
        char name[128] = {0};

        FD_ZERO(&fdset);
        FD_SET(clientSockFd, &fdset);

        if (g_server->g_running == 0) {
            break;
        }

        ret = select(clientSockFd + 1, &fdset, NULL, NULL, &tv);
        if (ret <= 0) {
            continue;
        }

        recvLen = SocketRecv(clientSockFd, rBuf, sizeof(rBuf), 0);
        if (recvLen < 0) {
            break;
        }

        if (GetBufferInfo(rBuf, NULL, '\r', method, sizeof(method)) < 0) {
            continue;
        }

        if (!strcmp(method, "SETUP")) {
            char tmp[40] = {0};
            sscanf(rBuf, "SETUP\r\nRTP/1.0 CMD:%S\r\nTransport:RTP/AVP;client_port=%d\r\n", tmp, &clientUPort);
            if (!strcmp(tmp, "RECV")) {
                cmd = CMD_READ;
            } else if (!strcmp(tmp, "SEND")) {
                cmd = CMD_WRITE;
            } else {
                cmd = CMD_NULL;
            }
            RequestSetupAck(sBuf, cmd, clientUPort);
        } else if (strcmp(method, "PLAY")) {
            play = 1;
            if (cmd == CMD_WRITE) {
                GetFileInfo(rBuf, name, sizeof(name), &fileSize);
                if (g_server->g_dialog) {
                    char msgBuf[256] = {0};
                    sprintf(msgBuf, "是否接收手机发来的文件:%s?", name);
                    if (g_server->g_dialog(g_server->g_data, (const char *)msgBuf, DIALOG_SELECT, 0) != 1) {
                        cmd = CMD_NULL;
                        fileSize = 0;
                        play = 0;
                        RequestPlayAck(sBuf, cmd, name, fileSize);
                        SocketSend(clientSockFd, sBuf, strlen(sBuf), 0);
                        continue;
                    }
                }
                sprintf(filename, RECV_FILE_PATH"%s", name);
                pthread_mutex_lock(&(g_server->g_mutex));
                g_server->g_fileList->PushBack((char *)name);
                pthread_mutex_unlock(&(g_server->g_mutex));
            }

            RequestPlayAck(sBuf, cmd, name, fileSize);
        } else {
            continue;
        }

        SocketSend(clientSockFd, sBuf, strlen(sBuf), 0);

        if (play) {
            FILE *pFile = NULL;

            if (cmd == CMD_READ) {
                pFile = fopen(filename, "rb");
                if (pFile != NULL) {
                    SocketSendFile(pFile, fileSize, SERVER_RTP_PORT, ip);
                }
            } else if (cmd == CMD_WRITE) {
                pFile = fopen(filename, "wb");
                if (pFile != NULL) {
                    SocketRecvFileWithProgress(pFile, fileSize, SERVER_RTP_PORT, g_server->g_dialog, g_server->g_data);
                }
            }

            cmd = -1;
            play = 0;
            fileSize = 0;

            if (pFile != NULL) {
                fclose(pFile);
                pFile = NULL;
            }
        }
    }

    close(clientSockFd);

    return NULL;
}
// ***************************************************** file recv task thread  end *************************************************************************** //
// ***************************************************** file server task thread start ************************************************************************ //

static void pipe_signal(int signo)
{
}

static void *FileServerProcess(void *params)
{
    int serverTcpSockfd = -1;
    pthread_t bstServerThread = 0;

    signal(SIGPIPE, pipe_signal);

    if (pthread_create(&bstServerThread, NULL, ServerBroadcast, &bstServerThread) < 0) {
        SER_ERR("create ServerBroadcast thread failed!");
        bstServerThread = 0;
    }

    serverTcpSockfd = SocketOpen(SERVER_PORT, (char *)"0.0.0.0");

    if (serverTcpSockfd < 0) {
        SER_ERR("SocketOpen failed!");
        goto PROCESS_EXIT;
    }

    while (1) {
        ClientInfo cf = {0};
        int ret = 0;
        char ip[40] = {0};
        int port = 0;
        pthread_t clientThread = -1;
        int clientSockfd = -1;
        fd_set fdset;
        struct timeval tv = {5, 0};

        g_server->g_fileIsTrans = 0;

        FD_ZERO(&fdset);
        FD_SET(serverTcpSockfd, &fdset);

        if (g_server->g_running == 0) {
            break;
        }

        ret = select(serverTcpSockfd + 1, &fdset, NULL, NULL, &tv);
        if (ret < 0) {
            SER_ERR("select failed! \n");
            break;
        } else if (ret == 0) {
            continue;
        }

        g_server->g_fileIsTrans = 1;

        clientSockfd = SocketAcceptClient(serverTcpSockfd, ip, sizeof(ip), &port);
        if (clientSockfd < 0) {
            SER_ERR("SocketAcceptClient failed!");
            break;
        }

        SER_DBG("Client has been connectted!");
        SER_DBG("client ip : %s, port : %d\n", ip, port);

        cf.fd = clientSockfd;
        (void)strcpy_s(cf.ip, sizeof(cf.ip), ip);

        if (pthread_create(&clientThread, NULL, ClientConnectProcess, (void *)&cf) < 0) {
            SER_ERR("create ClientConnectProcess failed! \n");
            continue;
        }
        pthread_detach(clientThread);
    }

PROCESS_EXIT:
    if (bstServerThread > 0) {
        pthread_cancel(bstServerThread);
        bstServerThread = 0;
    }

    if (serverTcpSockfd >= 0) {
        SocketClose(serverTcpSockfd);
        serverTcpSockfd = -1;
    }

    g_server->g_running = 0;

    return NULL;
}

// ***************************************************** file server task thread end ************************************************************************** //

int FileServerInit(CheckDialog dialog, void *data)
{
    int ret = 0;
printf("[%s|%d] \n", __func__, __LINE__);
    if (access(RECV_FILE_PATH, R_OK) != 0) {
        mkdir(RECV_FILE_PATH, FILE_MODE_ALL);
    }
printf("[%s|%d] \n", __func__, __LINE__);
    if (g_server != NULL) {
        SER_ERR("file server has been inited!");
        return 1;
    }
printf("[%s|%d] \n", __func__, __LINE__);
    g_server = (FileServer *)malloc(sizeof(FileServer));
    if (g_server == nullptr) {
        SER_ERR("OOM!");
        return -1;
    }
    memset(g_server, 0x00, sizeof(FileServer));
printf("[%s|%d] \n", __func__, __LINE__);
    g_server->g_fileList = new List<string>();
printf("[%s|%d] \n", __func__, __LINE__);
    if (pthread_mutex_init(&(g_server->g_mutex), NULL) < 0) {
        SER_ERR("pthread_mutex_init failed! errno = %d", errno);
        ret = -1;
        goto INIT_EXIT;
    }
printf("[%s|%d] \n", __func__, __LINE__);
    g_server->g_mutexInit = 1;
    g_server->g_dialog = dialog;
    g_server->g_data = data;
    g_server->g_running = 1;
printf("[%s|%d] \n", __func__, __LINE__);
    ret = pthread_create(&(g_server->g_thread), NULL, FileServerProcess, (void *)g_server);

INIT_EXIT:
    if (ret < 0) {
        if (g_server != NULL) {
            if (g_server->g_mutexInit) {
                pthread_mutex_destroy(&(g_server->g_mutex));
                g_server->g_mutexInit = 0;
            }

            free(g_server);
            g_server = NULL;
        }
        SER_ERR("FileServerInit failed!");
    } else {
        pthread_detach(g_server->g_thread);
    }
printf("[%s|%d] ret = %d\n", __func__, __LINE__, ret);
    return ret;
}

void FileServerDeinit(void)
{
    if (g_server != NULL) {
        if (g_server->g_thread && g_server->g_running) {
            g_server->g_running = 0;
        }
        if (g_server->g_mutexInit) {
            pthread_mutex_destroy(&(g_server->g_mutex));
            g_server->g_mutexInit = 0;
        }

        free(g_server);
        g_server = NULL;
    }
}

int FileServerGetTotal()
{
    int total = 0;

    if (g_server == NULL) {
        return -1;
    }

    pthread_mutex_lock(&(g_server->g_mutex));
    total = g_server->g_fileList->Size();
    pthread_mutex_unlock(&(g_server->g_mutex));

    return total;
}

int FileServerPopupFile(char *buff, int size)
{
    int ret = -1;

    if (g_server == NULL || buff == NULL || size <= 0) {
        return -1;
    }

    pthread_mutex_lock(&(g_server->g_mutex));

    if (g_server->g_fileList->Size() > 0) {
        if (g_server->g_fileList->Head() != nullptr) {
            char *data = (char *)g_server->g_fileList->Back().c_str();
            if (data != nullptr) {
                (void)strncpy_s(buff, size, data, strlen(data));
                ret = 0;
            }
            g_server->g_fileList->PopFront();
        }
    }

    pthread_mutex_unlock(&(g_server->g_mutex));

    return ret;
}

int FileServerIsUpdate(void)
{
    int ret = 0;

    if (g_server == NULL) {
        return -1;
    }

    pthread_mutex_lock(&(g_server->g_mutex));
    ret = g_server->g_fileList->Size();
    pthread_mutex_unlock(&(g_server->g_mutex));

    return ret > 0 ? 1 : 0;
}

void FileServerSetDialog(CheckDialog dialog, void *data)
{
    g_server->g_dialog = dialog;
    g_server->g_data = data;
}
